package com.ruoyi.web.controller.system;

import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.config.RuoYiConfig;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.domain.entity.system.*;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.FileUtils;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.config.ServerConfig;
import com.ruoyi.handler.socket.SocketMessageHandler;
import com.ruoyi.manager.SocketChannelManager;
import com.ruoyi.system.mapper.SysBoatShiplineMapper;
import com.ruoyi.system.mapper.SysShiplineMapper;
import com.ruoyi.system.service.ISysBoatService;
import com.ruoyi.system.service.ISysFenceService;
import com.ruoyi.system.service.ISysShiplineService;
import com.ruoyi.system.service.ISysWharfService;
import lombok.Data;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 船只信息Controller
 *
 * @author zjw
 * @date 2023-06-21
 */
@RestController
@RequestMapping("/system/boat")
public class SysBoatController extends BaseController {
    @Autowired
    private ISysBoatService sysBoatService;

    @Autowired
    private ServerConfig serverConfig;

    @Autowired
    private ISysShiplineService sysShiplineService;

    @Autowired
    private ISysWharfService sysWharfService;

    @Autowired
    private ISysFenceService sysFenceService;

    @Resource
    private SysBoatShiplineMapper boatShiplineMapper;

    @Resource
    private SysShiplineMapper sysShiplineMapper;

    @Data
    public static class DeleteBoatPicReqBody {
        private Long boatId;
        private String fileName;
    }

    /**
     * 查询船只信息列表
     */
    @PreAuthorize("@ss.hasPermi('system:boat:list')")
    @GetMapping("/list")
    public TableDataInfo list(SysBoat sysBoat) {
        Long scenicId = sysBoat.getScenicId();
        if (Objects.nonNull(scenicId) && scenicId == 0) { //景区id为0即为查询所有景区的船只列表
            sysBoat.setScenicId(null);
        }
        Long wharfId = sysBoat.getWharfId();
        if (Objects.nonNull(wharfId) && wharfId == 0) { //码头id为0即为查询当前景区下所有码头的船只列表
            sysBoat.setWharfId(null);
        }

        startPage();
        List<SysBoat> list = sysBoatService.selectSysBoatList(sysBoat);
        return getDataTable(list);
    }

    /**
     * 根据景区id获取景区下的所有船只信息。
     *
     * @param scenicId
     * @return
     */
    @GetMapping("/getBoatListByScenicId/{scenicId}")
    public AjaxResult getBoatListByScenicId(@PathVariable("scenicId") Long scenicId) {
        List<SysBoat> boatList = sysBoatService.getBoatListByScenicId(scenicId);
        return success(boatList);
    }

    /**
     * 导出船只信息列表
     */
    @PreAuthorize("@ss.hasPermi('system:boat:export')")
    @Log(title = "船只信息", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, SysBoat sysBoat) {
        List<SysBoat> list = sysBoatService.selectSysBoatList(sysBoat);
        ExcelUtil<SysBoat> util = new ExcelUtil<SysBoat>(SysBoat.class);
        util.exportExcel(response, list, "船只信息数据");
    }

    /**
     * 获取船只信息详细信息
     */
    @PreAuthorize("@ss.hasPermi('system:boat:query')")
    @GetMapping(value = "/{boatId}")
    public AjaxResult getInfo(@PathVariable("boatId") Long boatId) {
        SysBoat sysBoat = sysBoatService.selectSysBoatByBoatId(boatId);
        if (Objects.nonNull(sysBoat)) {
            AjaxResult ajax = AjaxResult.success();
            List<SysShipline> sysShiplines = sysShiplineService.selectShiplineListByScenicId(sysBoat.getScenicId());
            List<SysFence> fences = sysFenceService.selectFenceListByScenicId(sysBoat.getScenicId());
            ajax.put(AjaxResult.DATA_TAG, sysBoat);
            ajax.put("shiplines", sysShiplines);
            ajax.put("fences", fences);
            return ajax;
        } else {
            return AjaxResult.error("船只不存在！");
        }

    }

    /**
     * 新增船只信息
     */
    @PreAuthorize("@ss.hasPermi('system:boat:add')")
    @Log(title = "船只信息", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody SysBoat sysBoat) {
        return toAjax(sysBoatService.insertSysBoat(sysBoat));
    }

    /**
     * 修改船只信息
     */
    @PreAuthorize("@ss.hasPermi('system:boat:edit')")
    @Log(title = "船只信息", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody SysBoat sysBoat) {
        sysBoat.setUpdateBy(getUsername());
        sysBoat.setUpdateTime(DateUtils.getNowDate());

        Long boatId = sysBoat.getBoatId();

        //判断是否包含码头的数据
        Long wharfId = sysBoat.getWharfId();
        if (Objects.nonNull(wharfId) && wharfId != 0) { //新增或切换了码头
            SysWharf sysWharf = sysWharfService.selectWharfByWharfId(wharfId);
            if (Objects.nonNull(sysWharf)) {
                SocketMessageHandler.sendWharfInfoToAssignedOnlineBoat(boatId, sysWharf);
            } else {
                SocketMessageHandler.sendWharfInfoToAssignedOnlineBoat(boatId, null);
            }
        } else { //未设置或删除了码头
            SocketMessageHandler.sendWharfInfoToAssignedOnlineBoat(boatId, null);
        }

        Long[] shiplineIds = sysBoat.getShiplineIds();
        //判断是否包含自动航线的数据
        if (Objects.nonNull(shiplineIds) && shiplineIds.length > 0) {
            // 删除船只与自动航线的所有关联
            boatShiplineMapper.deleteSysBoatShiplineByBoatId(boatId);
            //新增船只与自动航线的关联
            insertBoatShipline(boatId, shiplineIds);

            Long firstShiplineId = shiplineIds[0];
            SysShipline sysShipline = sysShiplineMapper.selectSysShiplineByShiplineId(firstShiplineId);
            if (Objects.nonNull(sysShipline)) {
                SocketMessageHandler.sendShiplineInfoToAssignedOnlineBoat(boatId, sysShipline);
            } else {
                SocketMessageHandler.sendShiplineInfoToAssignedOnlineBoat(boatId, null);
            }
        } else {
            SocketMessageHandler.sendShiplineInfoToAssignedOnlineBoat(boatId, null);

            // 删除船只与自动航线的所有关联
            boatShiplineMapper.deleteSysBoatShiplineByBoatId(boatId);
        }

        //判断是否包含电子围栏的数据
        Long fenceId = sysBoat.getFenceId();
        if (Objects.nonNull(fenceId) && fenceId != 0) {
            SysFence sysFence = sysFenceService.selectFenceById(fenceId);
            if (Objects.nonNull(sysFence)) {
                SocketMessageHandler.sendFenceInfoToAssignedOnlineBoat(boatId, sysFence);
            } else {
                SocketMessageHandler.sendFenceInfoToAssignedOnlineBoat(boatId, null);
            }
        } else {
            SocketMessageHandler.sendFenceInfoToAssignedOnlineBoat(boatId, null);
        }

        int row = sysBoatService.updateSysBoat(sysBoat);

        if (row > 0) { //每次更新了船只信息后都需要同步更新下在线船端的船只信息
            SysBoat updatedSysBoat = sysBoatService.selectSysBoatByBoatId(sysBoat.getBoatId());
            SocketChannelManager.updateOnlineBoatInfo(updatedSysBoat);
        }

        return toAjax(row);
    }

    private void insertBoatShipline(Long boatId, Long[] shiplineIds) {
        if (StringUtils.isNotEmpty(shiplineIds)) {
            // 新增用户与角色管理
            List<SysBoatShipline> list = new ArrayList<SysBoatShipline>(shiplineIds.length);
            for (Long shiplineId : shiplineIds) {
                SysBoatShipline bs = new SysBoatShipline();
                bs.setBoatId(boatId);
                bs.setShiplineId(shiplineId);
                list.add(bs);
            }
            boatShiplineMapper.batchBoatShipline(list);
        }
    }

    /**
     * 删除船只信息
     */
    @PreAuthorize("@ss.hasPermi('system:boat:remove')")
    @Log(title = "船只信息", businessType = BusinessType.DELETE)
    @DeleteMapping("/{boatIds}")
    public AjaxResult remove(@PathVariable Long[] boatIds) {
        return toAjax(sysBoatService.deleteSysBoatByBoatIds(boatIds));
    }

    /**
     * 上传船只图片。
     */
    @PostMapping("/uploadBoatPic")
    public AjaxResult uploadBoatPic(MultipartFile file) throws Exception {
        try {
            // 获取船只图片上传路径
            String filePath = RuoYiConfig.getBoatPicPath();
            // 上传并返回新文件名称
            String fileName = FileUploadUtils.upload(filePath, file);
            String url = serverConfig.getUrl() + fileName;

            AjaxResult ajax = AjaxResult.success();
            ajax.put("url", url);
            ajax.put("fileName", fileName);
            ajax.put("newFileName", FileUtils.getName(fileName));
            ajax.put("originalFilename", file.getOriginalFilename());
            return ajax;
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }

    /**
     * 删除船只图片。
     */
    @PostMapping("/deleteBoatPic")
    public AjaxResult deleteBoatPic(@RequestBody DeleteBoatPicReqBody reqBody) throws Exception {
        try {
            Long boatId = reqBody.getBoatId();
            String fileName = reqBody.getFileName();
            // 获取船只图片上传路径
            String filePath = RuoYiConfig.getBoatPicPath();
            // 上传并返回新文件名称
            String deletefileName = filePath + fileName;
            boolean deleteFlag = FileUtils.deleteFile(deletefileName);

            if (deleteFlag) {
                SysBoat sysBoat = new SysBoat();
                sysBoat.setBoatId(boatId);
                sysBoat.setBoatPic("");
                sysBoatService.updateSysBoat(sysBoat);

                return success();
            } else {
                return error();
            }
        } catch (Exception e) {
            return AjaxResult.error(e.getMessage());
        }
    }
}
